package v1

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"zimuzu_cvn_web_api/config"
	"zimuzu_cvn_web_api/model"
	. "zimuzu_cvn_web_api/pkg/e"
	"zimuzu_cvn_web_api/pkg/errno"
	"zimuzu_cvn_web_api/router/api"
	"zimuzu_cvn_web_api/router/api/app/middleware"
	"zimuzu_cvn_web_api/service"
)

type UserAPI struct {
}

func (a UserAPI) Name() string {
	return "user API"
}

func (a UserAPI) Bind() {
	userAuthAPI := config.C.Router.Group("/v1/app/user", middleware.TrackLog(), middleware.AuthMiddleware())
	{
		userAuthAPI.GET("amountInfo", amountInfo)
		userAuthAPI.POST("loginPassword/set", updatePassword)
		userAuthAPI.GET("info", userInfo)
		userAuthAPI.GET("usage/set", userUsageSet)
		userAuthAPI.GET("usage/get", userUsageGet)
		userAuthAPI.GET("pay/checkCode", checkCode)
		userAuthAPI.GET("pay/checkPassword", checkPassword)
		userAuthAPI.GET("pay/setPassword", setPayPassword)
		userAuthAPI.GET("miningRouterList", miningRouterList)
		userAuthAPI.GET("chart", chartUser)

	}

	userAPI := config.C.Router.Group("/v1/app/user", middleware.TrackLog())
	{
		userAPI.GET("password/checkCode", checkResetPasswordCode)
		userAPI.POST("password/set", resetPassword)
		userAPI.GET("get/uid", getUid)
	}
}

// 根据用户名获取uid
// Auth: hzp
func getUid(c *gin.Context) {
	nickName := c.Query("name")
	// 判断用户输入的用户名是否已经注册过
	existsUser, _ := model.GetUserByName(config.C.DB.DB, nickName)
	if existsUser.Uid > 0 {
		errno.OK.Info = "获取成功"
		api.SendResponse(c, errno.OK, existsUser.Uid)
		return
	}
	api.SendResponse(c, errno.RecordError, nil)
	return
}

func chartUser(c *gin.Context) {
	var params model.ChartUserParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}
	if params.ShowType == 0 {
		params.ShowType = 1
	}
	if params.Source == 0 {
		params.Source = model.NodeTypeRouter
	}
	uid, _ := service.GetUserIdByRequest(c)
	re, err := service.GetClientRouterUserData(uid, params.NodeId, params.ShowType, params.Source)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "获取成功"
	api.SendResponse(c, errno.OK, re)
}

/*
 * @ Author: hupfei
 * @ Description: 挖矿设备列表
 **/
type miningNodeListParams struct {
	Source int `form:"source"`
	Page   int `form:"page"`
	Per    int `form:"per"`
}

func miningRouterList(c *gin.Context) {
	var params miningNodeListParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}
	if params.Source == 0 {
		params.Source = model.NodeTypeRouter
	}
	if params.Page == 0 {
		params.Page = 1
	}
	uid, _ := service.GetUserIdByRequest(c)
	re, err := service.GetMiningNodeList(uid, params.Source, params.Per, params.Page)
	if err != nil {
		api.SendResponse(c, errors.New("查询挖矿节点列表失败"), nil)
		return
	}

	errno.OK.Info = "获取挖矿节点列表成功"
	api.SendResponse(c, errno.OK, re)
	return
}

type amountInfoResponseData struct {
	TotalAmount      string  `json:"totalAmount"`
	Currency         string  `json:"currency"`
	AbleCvntAmount   float64 `json:"ableCvntAmount"`
	AbleEthAmount    float64 `json:"ableEthAmount"`
	AbleUsdtAmount   float64 `json:"ableUsdtAmount"`
	UnableCvntAmount float64 `json:"unableCvntAmount"`
	UnableEthAmount  float64 `json:"unableEthAmount"`
	UnableUsdtAmount float64 `json:"unableUsdtAmount"`
	TotalCvntAmount  string  `json:"totalCvntAmount"`
	TotalCvntUsdt    string  `json:"totalCvntUsdt"`
	AbleCvntUsdt     string  `json:"ableCvntUsdt"`
	TotalEthAmount   float64 `json:"totalEthAmount"`
	TotalEthUsdt     float64 `json:"totalEthUsdt"`
	TotalUsdtAmount  float64 `json:"totalUsdtAmount"`
	InvitationUrl    string  `json:"invitationUrl"`
}

//账户信息
func amountInfo(c *gin.Context) {
	uid, _ := service.GetUserIdByRequest(c)
	//账户CVNT信息
	cvntAmount, err := service.GetUserCvnAmountByUid(uid)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}
	usdtAmount, err := service.GetUserUsdtAmountByUid(uid)
	if err != nil {
		api.SendResponse(c, errno.DbSearchError, nil)
		return
	}

	_, cvntUsdPrice, err := service.GetCvntPrice()
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var amountInfo amountInfoResponseData
	amountInfo.Currency = "USD"
	amountInfo.AbleCvntAmount = cvntAmount.Balance
	amountInfo.UnableCvntAmount = cvntAmount.FrozenBalance

	totalCvntAmount := cvntAmount.Balance + cvntAmount.FrozenBalance
	amountInfo.TotalCvntAmount = fmt.Sprintf("%.8f", totalCvntAmount)
	amountInfo.TotalCvntUsdt = fmt.Sprintf("%.2f", totalCvntAmount*cvntUsdPrice)
	amountInfo.AbleCvntUsdt = fmt.Sprintf("%.2f", cvntAmount.Balance*cvntUsdPrice)

	loginToken, _ := service.GetLoginTokenCache(uid, service.LoginPlatformApp)
	amountInfo.InvitationUrl = config.C.WalletH5Domain + "/app.html#/invitation?token=" + loginToken

	amountInfo.AbleUsdtAmount = usdtAmount.Balance
	amountInfo.TotalUsdtAmount = usdtAmount.Balance
	amountInfo.TotalAmount = fmt.Sprintf("%.2f", totalCvntAmount*cvntUsdPrice+amountInfo.TotalUsdtAmount)

	errno.OK.Info = "获取信息成功"
	api.SendResponse(c, errno.OK, amountInfo)
	return
}

type userInfoResponseData struct {
	Uid           int64  `json:"uid"`
	Name          string `json:"name"`
	TaskWallUrl   string `json:"taskWallUrl"`
	Area          int    `json:"area"`
	Phone         string `json:"phone"`
	HelpUrl       string `json:"helpUrl"`
	DealUrl       string `json:"dealUrl"`
	InvitationUrl string `json:"invitationUrl"`
}

// 用户个人信息详情 3.6.1
// Auth: hzp
func userInfo(c *gin.Context) {
	data := userInfoResponseData{}
	uid, err := service.GetUserIdByRequest(c)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	Info, err := service.GetUserInfo(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	//任务墙地址
	shopToken := service.GetShopTokenCache(Info.Uid)
	taskWallUrl := service.GetTaskDomainUrl(Info.Uid, shopToken)

	data.Uid = Info.Uid
	data.Name = Info.Nickname
	data.Area = Info.PhoneArea
	data.Phone = Info.PhoneNumber
	data.TaskWallUrl = taskWallUrl
	loginToken, _ := service.GetLoginTokenCache(uid, service.LoginPlatformApp)
	data.InvitationUrl = config.C.WalletH5Domain + "/app.html#/invitation?token=" + loginToken
	data.HelpUrl = config.C.WalletH5Domain + "/app.html#/help"
	data.DealUrl = config.C.WalletH5Domain + "/app.html#/user-argeement"

	errno.OK.Info = "查询个人信息成功"
	api.SendResponse(c, errno.OK, data)
	return
}

// 使用设置 3.6.2
// Auth: hzp
func userUsageSet(c *gin.Context) {

	uid, err := service.GetUserIdByRequest(c)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var params model.UsageMode
	err = c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	err = service.UsageSet(uid, params.Language, params.Currency)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	errno.OK.Info = "设置成功"
	api.SendResponse(c, errno.OK, nil)
	return
}

// 查询 使用设置
// Auth: hzp
func userUsageGet(c *gin.Context) {

	uid, err := service.GetUserIdByRequest(c)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	data, err := service.UsageGet(uid)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	errno.OK.Info = "查询成功"
	api.SendResponse(c, errno.OK, data)
	return
}

// 3.6.4 修改支付密码
// Auth: hzp
func checkPassword(c *gin.Context) {

	uid, err := service.GetUserIdByRequest(c)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var params model.PasswordModel
	err = c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	Info, err := service.GetUserInfo(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	if !CheckMd5Password(params.Password, Info.Password, Info.Salt) {
		api.SendResponse(c, errno.ErrPasswordIncorrect, nil)
		return
	}

	var data model.Uuid
	data.U, err = service.SetRedisU(uid, 10*TimeFormatMin)
	if data.U == "" {
		api.SendResponse(c, errno.SystemErr, nil)
		return
	}

	errno.OK.Info = "验证成功"
	api.SendResponse(c, errno.OK, data)
	return
}

// 3.6.4 第四步
// Auth: hzp
type checkCodeParams struct {
	Code int    `form:"code" json:"code" binding:"required"`
	U    string `form:"u" json:"u" binding:"required"`
}

func checkCode(c *gin.Context) {

	uid, err := service.GetUserIdByRequest(c)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var params checkCodeParams
	err = c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	Info, err := service.GetUserInfo(uid)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	// 去校验 u 是否正确
	ok := service.IsPayPasswordChecked(uid, params.U)
	if !ok {
		api.SendResponse(c, errno.PhoneCodeCheckExpire, nil)
		return
	}

	// 校验验证码
	if errValid := service.ValidateCode(Info.PhoneNumber, service.SendCodeScenePay, params.Code); errValid != nil {
		api.SendResponse(c, errValid, nil)
		return
	}

	var data model.Uuid
	data.U, err = service.SetRedisU(uid, 10*TimeFormatMin)
	if data.U == "" {
		api.SendResponse(c, errno.SystemErr, nil)
		return
	}

	errno.OK.Info = "验证成功"
	api.SendResponse(c, errno.OK, data)
	return
}

// 3.6.4 第五步
// Auth: hzp
type setPayPasswordParams struct {
	Password string `form:"password" json:"password" binding:"required"`
	U        string `form:"u" json:"u"`
}

func setPayPassword(c *gin.Context) {

	uid, err := service.GetUserIdByRequest(c)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	var params setPayPasswordParams
	err = c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	// 去校验 u 是否正确
	// 新注册的初始化支付密码不需要校验上一步
	if !service.CheckRegMark(uid) {
		ok := service.IsPayPasswordChecked(uid, params.U)
		if !ok {
			api.SendResponse(c, errno.SignError, nil)
			return
		}
	}

	if params.Password == EmptyStrMd5 {
		api.SendResponse(c, errno.EmptyMd5PayPassword, nil)
		return
	}

	err = service.SetPayPassword(uid, params.Password)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "修改成功"
	api.SendResponse(c, errno.OK, nil)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 修改登录密码
 **/
type UpdatePasswordParams struct {
	OldPassword string `form:"old_password" json:"old_password" binding:"required"`
	NewPassword string `form:"new_password" json:"new_password" binding:"required"`
	U           string `form:"u" json:"u" binding:"required"`
}

func updatePassword(c *gin.Context) {
	// 检查参数是否为空
	var params UpdatePasswordParams
	err := c.ShouldBindWith(&params, binding.FormPost)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	uid, _ := service.GetUserIdByRequest(c)

	//去校验 u 是否正确
	//ok := service.IsPayPasswordChecked(uid, params.U)
	//if !ok {
	//	api.SendResponse(c, errno.PayPasswordCheckExpire, nil)
	//	return
	//}

	//获取缓存的用户信息
	user, err := service.GetUserInfo(uid)
	if err != nil || user.Uid < 1 {
		api.SendResponse(c, errno.ErrUserNotFound, nil)
		return
	}

	// 校验旧密码是否和数据库中的密码一致
	if !CheckPassword(params.OldPassword, user.Password, user.Salt) {
		api.SendResponse(c, errors.New("原密码错误"), nil)
		return
	}

	//修改登录密码
	ok, err := service.ModifyUserPassword(user.Uid, params.OldPassword, params.NewPassword, user.Salt)
	if err != nil || !ok {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "修改登录密码成功"
	api.SendResponse(c, errno.OK, nil)

	//清空token和shop_token
	_ = service.LoginOutClearToken(uid, service.LoginPlatformAll)

	//删除u
	service.DeleteU(uid, params.U)

	return
}

/*
 * @ Author: hupfei
 * @ Description: 校验重置登录密码的验证码
 **/
type CheckResetPasswordCodeParams struct {
	Code   int    `form:"code" json:"code" binding:"required"`
	Mobile string `form:"mobile" json:"mobile" binding:"required"`
	Area   int    `form:"area" json:"area" binding:"required"`
}

func checkResetPasswordCode(c *gin.Context) {
	var params CheckResetPasswordCodeParams
	err := c.ShouldBindWith(&params, binding.Query)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	//验证码校验
	errValid := service.ValidateCode(params.Mobile, service.SendCodeScenePassword, params.Code)
	if errValid != nil {
		api.SendResponse(c, errValid, nil)
		return
	}

	//根据手机号查询uid
	user, err := model.GetUserByMobile(config.C.DB.DB, params.Mobile, params.Area)
	if err != nil {
		api.SendResponse(c, errno.UserNotExist, nil)
		return
	}

	//获取u
	var data model.Uuid
	data.U, err = service.SetRedisU(user.Uid, 10*TimeFormatMin)
	if data.U == "" {
		api.SendResponse(c, errno.SystemErr, nil)
		return
	}
	errno.OK.Info = "验证通过"
	api.SendResponse(c, errno.OK, data)
	return
}

/*
 * @ Author: hupfei
 * @ Description: 重置登录密码
 **/
type ResetPasswordParams struct {
	Mobile   string `form:"mobile" json:"mobile" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
	U        string `form:"u" json:"u" binding:"required"`
	Area     int    `form:"area" json:"area" binding:"required"`
}

func resetPassword(c *gin.Context) {
	var params ResetPasswordParams
	err := c.ShouldBindWith(&params, binding.FormPost)
	if err != nil {
		api.SendResponse(c, errno.ParamsError, nil)
		return
	}

	//根据手机号查询用户信息
	user, err := model.GetUserByMobile(config.C.DB.DB, params.Mobile, params.Area)
	if err != nil {
		api.SendResponse(c, errno.UserNotExist, nil)
		return
	}

	//去校验 u 是否正确
	ok := service.IsPayPasswordChecked(user.Uid, params.U)
	if !ok {
		api.SendResponse(c, errno.PhoneCodeCheckExpire, nil)
		return
	}

	//修改登录密码
	ok, err = service.ModifyUserPassword(user.Uid, user.Password, params.Password, user.Salt)
	if err != nil || !ok {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "修改登录密码成功"
	api.SendResponse(c, errno.OK, nil)

	service.DeleteU(user.Uid, params.U)

	return
}
